package com.ray.util.baidu;

import java.util.HashMap;

import org.apache.log4j.Logger;
import org.json.JSONObject;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baidu.aip.imagesearch.AipImageSearch;
import com.ray.exception.ServiceException;
import com.ray.util.callback.CallBackApp;
import com.ray.util.redis.RedisCache;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * 百度相似图片搜索工具
 * @author Shensg
 *
 * 2018年10月5日
 * 
 * 注意：
 * 	具有免费调用额度的接口，超过每天的免费额度后会返回错误码：17，错误信息：Open api daily request limit reached（每天流量超限额）
 */
public class BaiduSimilarPicSearchUtils {
	public static Logger logger = Logger.getLogger(BaiduSimilarPicSearchUtils.class);
	/**
	 * 相似图检索—入库-本地图片
	 * @param brief 检索时原样带回,最长256B。
	 * @param tags 	1 - 65535范围内的整数，tag间以逗号分隔，最多2个tag。样例："100,11" ；检索时可圈定分类维度进行检索
	 * @param image 本地地址
	 * @return
	 * 	log_id 唯一的log id，用于问题定位
	 * 	cont_sign	 输入图片签名，可用于删除
	 */
	public static JSONObject similarPicInsertForLocal(Brief brief,Tags tags,String image) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		HashMap<String, String> options = new HashMap<String, String>();
	    options.put("brief", brief.toJson());
	    options.put("tags", tags.getType());
	    JSONObject res = client.similarAdd(image, options);
	    if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	throw new ServiceException(res.toString());
	    }
		return res;
	}
	/**
	 * 相似图检索—检索-本地图片
	 * @param tags 	1 - 65535范围内的整数，tag间以逗号分隔，最多2个tag。样例："100,11" ；检索时可圈定分类维度进行检索
	 * @param image 本地地址
	 * @param tagLogic 检索时tag之间的逻辑， 0：逻辑and，1：逻辑or
	 * @param pn 分页功能，起始位置，例：0。未指定分页时，默认返回前300个结果；接口返回数量最大限制1000条，例如：起始位置为900，截取条数500条，接口也只返回第900 - 1000条的结果，共计100条
	 * @param rn 分页功能，截取条数，例：250
	 * @return	{
				    "result_num": 1,	//检索结果数
				    "result": [
				        {
				            "score": 0.97976700290421,//图片相关性，0-1
				            "brief": "./data/jay1.jpg",//入库原样放回
				            "cont_sign": "475124309,1080176642"//图片签名，可以用来删除图片或定位问题
				        }
				    ],
				    "log_id": 1968648150，//唯一的log id，用于问题定位
				    "has_more"：true//是否还有下一页，返回值：true、false；如果不分页，不用关注该字段
				}
	 * 
	 */
	public static JSONObject similarPicSelectForLocal(Tags tags,byte[] image,int tagLogic,int pn,int rn) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		// 传入可选参数调用接口
	    HashMap<String, String> options = new HashMap<String, String>();
	    options.put("tags", tags.getType());
	    options.put("tag_logic", tagLogic+"");
	    options.put("pn", pn+"");
	    options.put("rn", rn+"");
	    JSONObject res = client.similarSearch(image, options);
	    if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	throw new ServiceException(res.toString());
	    }
		return res;
	}
	/**
	 * 更新图库中图片的摘要和分类信息-本地图片（具体变量为brief、tags）
	 * @param brief 检索时原样带回,最长256B。
	 * @param tags 	1 - 65535范围内的整数，tag间以逗号分隔，最多2个tag。样例："100,11" ；检索时可圈定分类维度进行检索
	 * @param image
	 * @return
	 * 	log_id 唯一的log id，用于问题定位
	 */
	public static JSONObject similarPicUpdateForLocal(Brief brief,Tags tags,String image) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		// 传入可选参数调用接口
		HashMap<String, String> options = new HashMap<String, String>();
	    options.put("brief", brief.toJson());
	    options.put("tags", tags.getType());
	    JSONObject res = client.similarUpdate(image, options);
	    if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	throw new ServiceException(res.toString());
	    }
		return res;
	}
	/**
	 * 相似图检索—删除-本地
	 * @param contSign
	 * @param image
	 * @return
	 */
	public static JSONObject similarPicDeleteForLocal(String image) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		// 传入可选参数调用接口
		HashMap<String, String> options = new HashMap<String, String>();
		JSONObject res = client.similarDeleteByImage(image, options);
		if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	throw new ServiceException(res.toString());
	    }
		return res;
	}
	
	/**
	 * 相似图检索—入库-远程图片
	 * @param brief 检索时原样带回,最长256B。
	 * @param tags 	1 - 65535范围内的整数，tag间以逗号分隔，最多2个tag。样例："100,11" ；检索时可圈定分类维度进行检索
	 * @return
	 * 	log_id 唯一的log id，用于问题定位
	 * 	cont_sign	 输入图片签名，可用于删除
	 */
	public static JSONObject similarPicInsertForRemote(Brief brief,Tags tags,String url) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		HashMap<String, String> options = new HashMap<String, String>();
	    options.put("brief", brief.toJson());
	    options.put("tags", tags.getType());
	    byte[] img = ImageUtils.readUrl(url,"GET");
	    JSONObject res = client.similarAdd(img, options);
	    if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	if("18".equals(res.get("error_code").toString())) {
	    		//存入redis 等待处理
	    		logger.error("百度相似图片入库,存入redis等待处理");
	    		JedisPool pool = RedisCache.getPool();
	    		Jedis jedis = pool.getResource();
	    		JSONArray array = new JSONArray();
	    		array.add(JSON.toJSONString(brief));
	    		array.add(JSON.toJSONString(tags));
	    		array.add(JSON.toJSONString(url));
	    		jedis.rpush("similarPicInsertForRemote",array.toJSONString());  
	    		RedisCache.returnResource(pool,jedis);
	    	}
	    }else {
	    	logger.info(res.toString());
	    }
	    return res;
	}
	
	/**
	 * 相似图检索—检索-远程图片
	 * @param tags 	1 - 65535范围内的整数，tag间以逗号分隔，最多2个tag。样例："100,11" ；检索时可圈定分类维度进行检索
	 * @param image 本地地址
	 * @param tagLogic 检索时tag之间的逻辑， 0：逻辑and，1：逻辑or
	 * @param pn 分页功能，起始位置，例：0。未指定分页时，默认返回前300个结果；接口返回数量最大限制1000条，例如：起始位置为900，截取条数500条，接口也只返回第900 - 1000条的结果，共计100条
	 * @param rn 分页功能，截取条数，例：250
	 * @return	{
				    "result_num": 1,	//检索结果数
				    "result": [
				        {
				            "score": 0.97976700290421,//图片相关性，0-1
				            "brief": "./data/jay1.jpg",//入库原样放回
				            "cont_sign": "475124309,1080176642"//图片签名，可以用来删除图片或定位问题
				        }
				    ],
				    "log_id": 1968648150，//唯一的log id，用于问题定位
				    "has_more"：true//是否还有下一页，返回值：true、false；如果不分页，不用关注该字段
				}
	 * 
	 */
	public static JSONObject similarPicSelectForRemote(Tags tags,String url,int tagLogic,int pn,int rn) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		// 传入可选参数调用接口
	    HashMap<String, String> options = new HashMap<String, String>();
	    options.put("tags", tags.getType());
	    options.put("tag_logic", tagLogic+"");
	    options.put("pn", pn+"");
	    options.put("rn", rn+"");
	    byte[] img = ImageUtils.readUrl(url,"GET");
	    JSONObject res = client.similarSearch(img, options);
	    if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	throw new ServiceException(res.toString());
	    }
		return res;
	}
	/**
	 * 更新图库中图片的摘要和分类信息-远程图片（具体变量为brief、tags）
	 * @param brief 检索时原样带回,最长256B。
	 * @param tags 	1 - 65535范围内的整数，tag间以逗号分隔，最多2个tag。样例："100,11" ；检索时可圈定分类维度进行检索
	 * @param image
	 * @return
	 * 	log_id 唯一的log id，用于问题定位
	 */
	public static JSONObject similarPicUpdateForRemote(Brief brief,Tags tags,String url) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		// 传入可选参数调用接口
		HashMap<String, String> options = new HashMap<String, String>();
	    options.put("brief", brief.toJson());
	    options.put("tags", tags.getType());
	    byte[] img = ImageUtils.readUrl(url,"GET");
	    JSONObject res = client.similarUpdate(img, options);
	    if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	throw new ServiceException(res.toString());
	    }
		return res;
	}
	/**
	 * 相似图检索—删除-远程图片
	 * @param contSign
	 * @param url
	 * @return
	 */
	public static JSONObject similarPicDeleteForRemote(String url) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		// 传入可选参数调用接口
		HashMap<String, String> options = new HashMap<String, String>();
		byte[] img = ImageUtils.readUrl(url,"GET");
		JSONObject res = client.similarDeleteByImage(img, options);
		if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	if("18".equals(res.get("error_code").toString())) {
	    		//存入redis 等待处理
	    		logger.error("百度相似图片删除,存入redis等待处理");
	    		JedisPool pool = RedisCache.getPool();
	    		Jedis jedis = pool.getResource();
	    		jedis.rpush("similarPicDeleteForRemote",url);  
	    		RedisCache.returnResource(pool,jedis);
	    	}
	    }
		return res;
	}
	/**
	 * 相似图检索—删除-远程图片
	 * @param contSign
	 * @param url
	 * @return
	 */
	public static JSONObject similarPicDeleteForRemoteByContSign(String contSign) {
		AipImageSearch client =AipImageSearchUtil.getConfig();
		// 传入可选参数调用接口
		HashMap<String, String> options = new HashMap<String, String>();
		JSONObject res = client.similarDeleteBySign(contSign, options);
		if(res.has("error_code")) {
	    	logger.error(res.toString());
	    	if(res.has("error_code")) {
	    		System.out.println("similarPicDeleteForRemote错误"+res.get("error_code"));
		    	if("18".equals(res.get("error_code").toString())) {
		    		//存入redis 等待处理
		    		logger.error("百度相似图片删除,存入redis等待处理");
		    		JedisPool pool = RedisCache.getPool();
		    		Jedis jedis = pool.getResource();
		    		jedis.rpush("similarPicDeleteForRemote",contSign);  
		    		RedisCache.returnResource(pool,jedis);
		    	}
		    }
	    }else {
	    	logger.info(res.toString());
	    }
		return res;
	}
	
}
